#include <glib.h>
#include <gtk/gtk.h>
#include <SDL.h>
#include "racanhack.h"
#include "task.h"
#include "video.h"
#include "cave.h"
#include "player.h"
#include "monster.h"
#include "object.h"
#include "stair.h"
#include "floor.h"
#include "los.h"
#include "lookdown.h"
#include "main.h"

enum {
  LOOKDOWN_X = 120,
  LOOKDOWN_Y = 16,
  LOOKDOWN_GRID_SIZE = 8
};

static SDL_Surface *surface_lookdown_background;
static SDL_Surface *surface_lookdown_chip_map_pass;
static SDL_Surface *surface_lookdown_chip_player;
static SDL_Surface *surface_lookdown_chip_monster;
static SDL_Surface *surface_lookdown_chip_object;
static SDL_Surface *surface_lookdown_chip_stair;
static SDL_Surface *surface_lookdown;

void lookdown_trans_state(state (*fp)(struct _task *task), struct _lookdown *lookdown)
{
  if (lookdown->task != NULL) lookdown->task->alive = FALSE;
  lookdown->task = task_add(fp, lookdown);
}

void lookdown_init()
{
  SDL_Surface *s;
  SDL_Rect r;
  surface_lookdown_background = video_bmp_load("bmp/lookdown_background.bmp");
  s = video_bmp_load("bmp/lookdown_background.bmp");
  r.w = s->w;  r.h = s->h;
  r.x = 0;  r.y = 0;
  surface_lookdown = video_crop_alpha(s, &r, 128);
  SDL_FreeSurface(s);
  s = video_bmp_load("bmp/lookdown_chip.bmp");
  r.w = LOOKDOWN_GRID_SIZE;  r.h = LOOKDOWN_GRID_SIZE;
  r.x = LOOKDOWN_GRID_SIZE * 0;  r.y = 0;
  surface_lookdown_chip_map_pass = video_crop(s, &r);
  r.x = LOOKDOWN_GRID_SIZE * 1;  r.y = 0;
  surface_lookdown_chip_player = video_crop(s, &r);
  r.x = LOOKDOWN_GRID_SIZE * 2;  r.y = 0;
  surface_lookdown_chip_monster = video_crop(s, &r);
  r.x = LOOKDOWN_GRID_SIZE * 3;  r.y = 0;
  surface_lookdown_chip_object = video_crop(s, &r);
  r.x = LOOKDOWN_GRID_SIZE * 4;  r.y = 0;
  surface_lookdown_chip_stair = video_crop(s, &r);
  SDL_FreeSurface(s);
}

void lookdown_free()
{
  SDL_FreeSurface(surface_lookdown_background);
  SDL_FreeSurface(surface_lookdown_chip_map_pass);
  SDL_FreeSurface(surface_lookdown_chip_player);
  SDL_FreeSurface(surface_lookdown_chip_monster);
  SDL_FreeSurface(surface_lookdown_chip_object);
  SDL_FreeSurface(surface_lookdown_chip_stair);
  SDL_FreeSurface(surface_lookdown);
}

struct _lookdown *lookdown_add()
{
  struct _lookdown *lookdown;
  lookdown = &Lookdown;
  lookdown->mapdetect = FALSE;
  lookdown->mondetect = FALSE;
  lookdown->objdetect = FALSE;
  lookdown->sprite = video_sprite_add(Z_ORDER_LOOKDOWN);
  lookdown->task = NULL;
  return lookdown;
}

state lookdown_show(struct _task *task)
{
  struct _lookdown *lookdown;
  struct _coord c;
  SDL_Rect r;
  GList *li;
  struct _monster *monster;
  struct _object *object;
  struct _stair *stair;
  lookdown = (struct _lookdown *)task->pointer[0];
  if (!((keys[SDLK_LSHIFT]) ||
      (keys[SDLK_RSHIFT]))) {
    lookdown_trans_state(lookdown_hide, lookdown);
    return;
  };
  if (task->count != 0) return;
  SDL_SetColorKey(surface_lookdown, 0, 0);
  SDL_BlitSurface(surface_lookdown_background, NULL, surface_lookdown, NULL);
  for (c.x = 0; c.x < MAP_W; c.x++) {
    for (c.y = 0; c.y < MAP_H; c.y++) {
      if (is_map_pass(c)) {
	if ((lookdown->mapdetect == TRUE) ||
	    (is_map_passed(c))) {
	  r.x = c.x * LOOKDOWN_GRID_SIZE;
	  r.y = c.y * LOOKDOWN_GRID_SIZE;
	  r.w = LOOKDOWN_GRID_SIZE;
	  r.h = LOOKDOWN_GRID_SIZE;
	  SDL_BlitSurface(surface_lookdown_chip_map_pass, NULL, surface_lookdown, &r);
	};
      };
    };
  };
  for (li = g_list_first(curf->monster_list); li != NULL; li = g_list_next(li)) {
    monster = (struct _monster *)li->data;
    if ((lookdown->mondetect == TRUE) ||
	(is_los_onsight(monster->coord))) {
      r.x = monster->coord.x * LOOKDOWN_GRID_SIZE;
      r.y = monster->coord.y * LOOKDOWN_GRID_SIZE;
      r.w = LOOKDOWN_GRID_SIZE;
      r.h = LOOKDOWN_GRID_SIZE;
      SDL_BlitSurface(surface_lookdown_chip_monster, NULL, surface_lookdown, &r);
    };
  };
  for (li = g_list_first(curf->object_list); li != NULL; li = g_list_next(li)) {
    object = (struct _object *)li->data;
    if (object->task->fp == object_on_floor) {
      if ((lookdown->objdetect == TRUE) ||
	  (is_map_passed(object->coord))) {
	r.x = object->coord.x * LOOKDOWN_GRID_SIZE;
	r.y = object->coord.y * LOOKDOWN_GRID_SIZE;
	r.w = LOOKDOWN_GRID_SIZE;
	r.h = LOOKDOWN_GRID_SIZE;
	SDL_BlitSurface(surface_lookdown_chip_object, NULL, surface_lookdown, &r);
      };
    };
  };
  for (li = g_list_first(curf->stair_list); li != NULL; li = g_list_next(li)) {
    stair = (struct _stair *)li->data;
    if ((lookdown->mapdetect == TRUE) || (is_map_passed(stair->coord))) {
      r.x = stair->coord.x * LOOKDOWN_GRID_SIZE;
      r.y = stair->coord.y * LOOKDOWN_GRID_SIZE;
      r.w = LOOKDOWN_GRID_SIZE;
      r.h = LOOKDOWN_GRID_SIZE;
      SDL_BlitSurface(surface_lookdown_chip_stair, NULL, surface_lookdown, &r);
    };
  };
  r.x = Player.coord.x * LOOKDOWN_GRID_SIZE;
  r.y = Player.coord.y * LOOKDOWN_GRID_SIZE;
  r.w = LOOKDOWN_GRID_SIZE;
  r.h = LOOKDOWN_GRID_SIZE;
  SDL_BlitSurface(surface_lookdown_chip_player, NULL, surface_lookdown, &r);
  SDL_SetColorKey(surface_lookdown, SDL_SRCCOLORKEY | SDL_RLEACCEL, transparent);
  lookdown->sprite->x = LOOKDOWN_X;
  lookdown->sprite->y = LOOKDOWN_Y;
  lookdown->sprite->abs = TRUE;
  lookdown->sprite->surface = surface_lookdown;
}

state lookdown_hide(struct _task *task)
{
  struct _lookdown *lookdown;
  lookdown = (struct _lookdown *)task->pointer[0];
  lookdown->sprite->surface = NULL;
  if ((keys[SDLK_LSHIFT]) ||
      (keys[SDLK_RSHIFT])) {
    lookdown_trans_state(lookdown_show, lookdown);
  };
}

void lookdown_update()
{
  if (Lookdown.task->fp == lookdown_show) {
    lookdown_trans_state(lookdown_show, &Lookdown);
  };
}
